home *** CD-ROM | disk | FTP | other *** search
- /**
- * Geolocation object to fill in for Firefox's broken geolocation support
- * for extensions.
- *
- * Contacts Google's geolocation service, which uses a list of WiFi access
- * points and IP address to geolocate.
- *
- * @author chris
- */
-
- var GEOLOCATION = {
- ERROR_WIFI_NOT_AVAILABLE : -2147221231,
-
- /**
- * The cached last position.
- */
- _lastPosition : null,
-
- /**
- * Making the last position readonly from outside of the object.
- */
- get lastPosition() { return this._lastPosition; },
- set lastPosition() { throw Exception; },
-
- /**
- * @var hash
- * A list of callbacks that have registered with the geolocation service
- * to get notifications of new locations.
- */
- listeners : {},
-
- /**
- * Service initializer. Uses Firefox 3.5's wifi monitoring to determine change in location.
- */
- load : function () {
- var wifi_service = Components.classes["@mozilla.org/wifi/monitor;1"].getService(Components.interfaces.nsIWifiMonitor);
- wifi_service.startWatching(this);
- },
-
- /**
- * Service unloader. Cleans up after the initializer.
- */
- unload : function () {
- var wifi_service = Components.classes["@mozilla.org/wifi/monitor;1"].getService(Components.interfaces.nsIWifiMonitor);
- wifi_service.stopWatching(this);
- },
-
- /**
- * The callback function for the wifi listener.
- *
- * @param array accessPoints A list of WiFi access ponts.
- */
- onChange : function (accessPoints) {
- // Contact the Geolocation service and get the new coordinates.
- var _length = accessPoints.length;
-
- // The JSON request for the geolocation service.
- var request_body = {
- version: "1.1.0",
- host: "firefound.com",
- request_address: true
- };
-
- request_body.wifi_towers = [];
-
- if (_length > 0) {
- for (var i = 0; i < _length; i++) {
- // Include each wifi access point and its strength.
- request_body.wifi_towers.push(
- {
- "mac_address" : accessPoints[i].mac,
- "signal_strength": accessPoints[i].signal,
- "age": 0,
- "ssid": accessPoints[i].ssid
- }
- );
- }
- }
-
- // Ask Google for the geophysical location.
- var req = new XMLHttpRequest();
- req.open("POST", "http://www.google.com/loc/json", true);
- var self = this;
-
- req.onreadystatechange = function () {
- if (req.readyState == 4) {
- if (FIREFOUND.prefs.getBoolPref("debug")) {
- FIREFOUND.log("onChange: " + req.responseText);
- }
-
- var json = JSON.parse(req.responseText);
-
- if ("location" in json) {
- // Save this location for easy, painless access.
- self._lastPosition = json.location;
- self._lastPosition.wifi_towers = request_body.wifi_towers;
-
- for (listener in self.listeners) {
- // Notify all the listeners of a new location.
- self.listeners[listener].success(self._lastPosition);
- }
- }
- else {
- self.log("No location could be determined.");
- }
- }
- };
-
- req.send(JSON.stringify(request_body));
- },
-
- /**
- * Error callback for the WiFi listener. Not a big deal (unless it errors over and over).
- */
- onError : function (value) {
- if (value == GEOLOCATION.ERROR_WIFI_NOT_AVAILABLE) {
- // User does not have WiFi interface.
- // Just use the IP address.
- this.onChange([]);
- }
- else {
- this.log("WiFi Listener Error: " + value);
- }
- },
-
- QueryInterface: function(iid) {
- if (iid.equals(Components.interfaces.nsIWifiListener) ||
- iid.equals(Components.interfaces.nsISupports)) {
- return this;
- }
-
- throw Components.results.NS_ERROR_NO_INTERFACE;
- },
-
- /**
- * Public interface to the geolocation service.
- *
- * @param function The success callback.
- * @param function The error callback.
- * @param options Unused.
- */
-
- getCurrentPosition : function (successCallback, errorCallback, options) {
- if (this.lastPosition) {
- successCallback(this.lastPosition);
- }
- else {
- // An unlikely scenario, since the WIFI onchange will be called as soon as the service starts.
- // TODO Fetch the current access points and get the location.
- errorCallback("lastPosition is undefined");
- }
- },
-
- /**
- * Allows objects to register for notifications of position changes.
- *
- * @param function The success callback.
- * @param function The error callback.
- * @param options Unused.
- */
- watchPosition : function (successCallback, errorCallback, options) {
- // Use the current microtime as the id of the watcher.
- var watchId = new Date().getTime();
-
- this.listeners[watchId] = { success: successCallback, errors: errorCallback };
-
- return watchId;
- },
-
- /**
- * Removes a listener from the position change notification list.
- *
- * @param string The id of the listener.
- */
-
- clearWatch : function (watchId) {
- if (watchId in this.listeners) {
- delete this.listeners[watchId];
- }
- },
-
- /**
- * Log a message to the Error Console.
- *
- * @param string message
- */
- log : function (message) {
- var consoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
- consoleService.logStringMessage("GEOLOCATION: " + message);
- }
- };
-
- // Automatically load this service when it's included.
- addEventListener("load", function () { GEOLOCATION.load(); }, false);
- addEventListener("unload", function () { GEOLOCATION.unload(); }, false);